package com.message.tcp.ip.socket.client;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

import org.apache.log4j.Logger;
import org.jpos.iso.ISOException;
import org.jpos.iso.ISOMsg;
import org.jpos.iso.packager.GenericPackager;

import com.message.tcp.ip.socket.util.MessageDefinition;
import com.message.tcp.ip.socket.util.UtilPackage;

public class MessageClientImp implements MessageClient {
	private static final Logger logger = Logger.getLogger(MessageClientImp.class);
	private GenericPackager packager = MessageDefinition.getGenericPackager();
	private String serverHostname;
	private int port;
	private Socket clientSocket;
	public MessageClientImp(String serverHostName, String portNum){
		this.serverHostname = serverHostName;
		this.port = Integer.parseInt(portNum);
		try {
			clientSocket = new Socket(serverHostname,port);
		} catch (IOException e) {
			logger.debug("IOException occur while trying to access data",e);
			System.exit(1);
		}
		
	}
	@Override
	public void runEchoClient(byte[] input) throws UnknownHostException, IOException {
		try {
			sendBytes(input,0,input.length);
			byte[] data = readBytes();
			ISOMsg isoMsg = new ISOMsg();
			isoMsg.setPackager(packager);
			byte[] raw = UtilPackage.extractMessage(data);
			char[] dump = UtilPackage.asHex(raw).toCharArray();
			System.out.println(new String(raw));
			isoMsg.unpack(raw);
			UtilPackage.printLogger(isoMsg);
			for(int i=0;i<dump.length;i++){
				int count = i + 1;
				if(count%2==0)
					System.out.printf("%c ",dump[i]);
				else
					System.out.printf("%c",dump[i]);
				
				if(count % 32 == 0)
					System.out.print("\n");
			}
			
		} catch (UnknownHostException e) {
			logger.debug("UnknownHostException occur while trying to connect server", e);
			System.exit(1);
		} catch (IOException e) {
			logger.debug("IOException occur while trying to access data",e);
			System.exit(1);
		} catch (ISOException e) {
			logger.debug("ISOException occur while trying to extract data",e);
		}
		
	}
	
	private void sendBytes(byte[] data, int offset, int length) throws IOException {
		if(length < 0)
			throw new IllegalArgumentException("Negative length not allowed");
		if(offset < 0 || offset >= data.length)
			throw new IndexOutOfBoundsException("Out of bounds "+offset);
		OutputStream out = clientSocket.getOutputStream();
		DataOutputStream dos = new DataOutputStream(out);
		dos.writeInt(length);
		if(length > 0)
			dos.write(data, offset, length);
	}
	private byte[] readBytes() throws IOException{
		InputStream in = clientSocket.getInputStream();
		DataInputStream dis = new DataInputStream(in);
		int len = dis.readInt();
	    byte[] data = new byte[len];
	    if (len > 0) {
	        dis.readFully(data);
	    }
	    return data;
	}
}
